Skip to content

[7060][ADD] stock_acceptance_number, stock_acceptance_label: print acceptance labels from transfers - #13

Open
kanda999 wants to merge 21 commits into
18.0from
18.0-add-stock_acceptance_label
Open

kanda999 wants to merge 21 commits into
18.0from
18.0-add-stock_acceptance_label

Conversation

@kanda999

@kanda999 kanda999 commented Jul 29, 2026 •

Copy link
Copy Markdown

QT7060

Adds an acceptance label that is printed from transfers, three labels per A4 portrait sheet (one per horizontal band).

  • One label per transfer line, several transfers can be selected at once (Print > Acceptance Label). Cancelled lines are skipped, and the labels of a transfer stay together.
  • Acceptance Number is a new field on the transfer lines (Operations tab of the transfer), and may be left empty.
  • The label is a single table, one row per value: product name, acceptance number, model number (product internal reference), lot number, expiration date, arrival date, status area, and the product barcode (Code128).
  • Lot number and expiration date come from the lots of the line, so they stay blank until the lots are assigned in the Detailed Operations. A line received in several lots prints them all, separated by commas. The expiration date comes from product_expiry, which the module now depends on.
  • The field printed as the arrival date is selected in Inventory > Configuration > Settings > Acceptance Label > Arrival Date. Any date or datetime field of the transfer or of its lines can be selected, including fields added by other modules, and datetime fields are converted to the user time zone. The effective date of the transfer is used by default.
  • The status area is editable HTML in the same settings block. It opens filled in with the built-in area (□ 検査中 / ↓ / □ 適合 or □ 不合格) so that it only has to be adjusted; emptying it restores the built-in area, which follows the language of the printing user.

Verified on 2rbkk1: 13 tests pass, and the rendered PDF fits eight rows in each 98mm band in both English and Japanese.

kanda999 added 4 commits July 29, 2026 11:13
Add an acceptance label printed from transfers (3 per A4 portrait sheet), so
that the incoming goods can be tagged with their acceptance number and the
result of the acceptance test can be marked by hand on the label.
The date to be printed as the arrival date differs between operations, so the
effective date of the transfer cannot always be used. Let the field be selected
in the inventory settings, among the date and datetime fields of the transfer
and of its lines, and keep the effective date of the transfer as the default.
The goods are accepted per lot, so the lot number and the expiration date of
that lot belong on the label as well. They stay blank while the lots of the line
are unknown, and a line received in several lots prints them all.

The barcode becomes a row of the table like every other value, instead of a
picture below it, so that the whole label reads as a single form.

The status area is what differs the most between operations, so it moves to the
inventory settings as editable HTML. The built-in area is printed as long as the
setting is left empty, which keeps it translated.

Depends on product_expiry, which is where the expiration date of a lot comes
from.
The layout of the label was an asset of web.report_assets_common, which is
fetched over HTTP by wkhtmltopdf and shared by every report of the database. A
base URL that cannot be reached therefore produced a label without page breaks
nor fixed bands, silently, and the rules were loaded by reports that have no use
for them.

Move the rules into a style element of the report template, so that the layout
travels with the markup it applies to and the module needs no asset bundle. The
rendered PDF is unchanged.
@kanda999

Copy link
Copy Markdown
Author

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@kanda999

Copy link
Copy Markdown
Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 919233bb26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

class StockMove(models.Model):
_inherit = "stock.move"

acceptance_number = fields.Char(copy=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent differently numbered moves from merging

When a draft transfer contains otherwise merge-compatible moves with different acceptance numbers, the normal stock.move confirmation merge does not consider this newly added field, so the moves can collapse into one line and one acceptance number is discarded. Include acceptance_number among the distinct fields used when merging moves so each numbered line still produces its intended label.

Useful? React with 👍 / 👎.

Comment on lines +54 to +55
self.env["ir.config_parameter"].sudo().set_param(
STATUS_HTML_PARAM, False if is_html_empty(status_html) else status_html

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the built-in status area language-dependent

When the status parameter is initially unset, get_values() fills this transient field with the built-in area translated for the settings user's language, and saving Inventory settings—even without editing this field—persists that rendered HTML here. Subsequent reports then treat it as custom content and print that one language for every user instead of translating the built-in area for the printing user; leave the parameter unset when the submitted value is the built-in default.

Useful? React with 👍 / 👎.

@kanda999

Copy link
Copy Markdown
Author

@copilot

This comment was marked as off-topic.

@kanda999
kanda999 marked this pull request as ready for review August 17, 2026 10:55

@nobuQuartile nobuQuartile left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional review: LGTM

Comment thread stock_acceptance_label/models/res_config_settings.py
Comment thread stock_acceptance_label/models/stock_picking.py Outdated
@nobuQuartile

Copy link
Copy Markdown
Contributor

@AungKoKoLin1997
Could you continue the review?

Comment thread stock_acceptance_label/models/res_company.py Outdated
Comment on lines +21 to +22
@api.onchange("company_id")
def _onchange_company_id_acceptance_label(self):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we talked, please remove it if it is not necessary. You could consider default attribute if you want the default value.

Comment thread stock_acceptance_label/models/stock_move.py Outdated
@nobuQuartile

Copy link
Copy Markdown
Contributor

Pushed d412cd8 to 18.0-add-stock_acceptance_label, addressing the review comments and the two red checks.

Review comments

  • res_company.py (@AungKoKoLin1997): the arrival date default moved out of the field definition into _default_acceptance_label_arrival_date_field(). The same method is now the single fallback, through the new _get_acceptance_arrival_date_field(), so stock_move.py no longer repeats _get("stock.picking", "date_done").
  • res_config_settings.py (@AungKoKoLin1997): the onchange is gone (removed in 64ee06c); this drops the imports it left behind, which is what ruff was failing on. Dropping the prefill also settles the Codex comment about the built-in status area losing its translation: saving the settings untouched no longer persists the rendered HTML, so the area keeps following the language of the printing user until it is really edited.
  • stock_move.py (@AungKoKoLin1997): _get_acceptance_lots() now returns self.lot_ids.
  • Codex P2 on move merging: _prepare_merge_moves_distinct_fields() now includes acceptance_number, so two otherwise identical lines with different acceptance numbers are not collapsed into one on confirmation, and each still gets its label.

Tests

test_status_area_setting was asserting the prefill that the onchange used to do, which is what the test job was erroring on (TypeError: argument of type 'bool' is not iterable). It now checks the same behaviour from the printed side: built-in area while the setting is empty, the configured area once it is set, built-in again once it is emptied. Added test_numbered_lines_are_not_merged for the merge change.

15 tests pass locally (-u stock_acceptance_label --test-enable), and pre-commit run is clean.

README.rst and static/description/index.html were also behind the readme/ fragments from earlier commits; the text is hand-applied here rather than regenerated, to keep the diff free of docutils version churn.

 stock_acceptance_label/README.rst                        | 14 ++++---
 stock_acceptance_label/models/res_company.py             | 15 +++++---
 stock_acceptance_label/models/res_config_settings.py     |  3 +-
 stock_acceptance_label/models/stock_move.py              | 10 ++++--
 stock_acceptance_label/readme/CONFIGURE.md               |  4 +--
 stock_acceptance_label/static/description/index.html     | 13 +++++--
 stock_acceptance_label/tests/test_stock_acceptance_label.py | 30 +++++++++-----

@AungKoKoLin1997 AungKoKoLin1997 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: LGTM

Comment thread stock_acceptance_label/models/res_config_settings.py Outdated
Co-authored-by: Aung Ko Ko Lin (Quartile) <45355704+AungKoKoLin1997@users.noreply.github.com>
@nobuQuartile

Copy link
Copy Markdown
Contributor

@kanda999
Could you review this PR?

@nobuQuartile

Copy link
Copy Markdown
Contributor

@kanda999, could you review this PR?

The acceptance number was a plain field of the transfer line, so a line
received in several lots could only carry one number, and the lots kept
none of their own.

The detailed operations now hold the number, the transfer line summarizes
the numbers of its operations, and each lot keeps the numbers it was
received under. A line of a product without tracking is still numbered on
the line itself, which is carried over to its first detailed operation;
for a tracked product the field is read-only on the line and is entered
per lot instead.

The numbers of the lot are computed from its operations rather than
appended to on receipt, so that a number corrected, or a receipt cancelled
after the fact, drops out instead of staying on the lot for good.

Transfers can also be searched by acceptance number.
t and others added 7 commits September 29, 2026 03:48
…alog

The acceptance number was only added to the detailed operations list of
the Operations tab. The Move Detail dialog, opened from a transfer line,
renders its operations through another list view, so the field was
missing exactly where a tracked line is numbered per lot.

Both list views now carry it, anchored after the lot name rather than the
lot reference: only one of the two lot columns is shown at a time, and
anchoring on the last of them keeps the number next to the lot in either
case.

The two move line views moved to their own file, as they inherit views of
stock.move.line rather than of stock.picking.
The acceptance number is given when goods are received, so it is of no
use on a delivery, an internal transfer or a manufacturing operation.

The column is now hidden unless the operation type of the transfer is a
receipt, in each of the three lists that show it: the lines of the
transfer, the detailed operations opened from it, and the detailed
operations of a single line in the Move Detail dialog. Each one reads the
operation type the way its own neighbouring columns do, from the parent
record or from the context.

The transfer list and the search bar are left alone: they span operation
types, so there is nothing to gate them on.
A label carries one acceptance number and one lot, but it was printed per
transfer line. A line received in several lots had to squeeze them into a
single label, listing the lot numbers and the expiration dates as comma
separated strings that the reader had to pair up by position.

The label is now printed per detailed operation, which is what holds the
acceptance number and the lot. A line received in three lots prints three
labels, each with its own number, lot and expiration date, and the lot
and date rows became plain fields.

The helpers that read the label follow the operation: the arrival date
still resolves the configured field through the transfer or its line, and
the lot helpers that joined several lots are gone, having nothing left to
join.

The operations are created when the transfer is confirmed, so a transfer
still in draft now prints nothing where it used to print its lines.
Limit the operations the acceptance numbers of a lot are read from to
those of receipts. The operation type is taken from the transfer line,
whose type is stored, rather than from the operation, whose type is only
known once it is attached to a transfer.
Comment thread stock_acceptance_number/models/stock_move.py
Comment thread stock_acceptance_label/models/stock_move.py Outdated
Comment thread stock_acceptance_label/models/stock_move_line.py Outdated
Comment thread stock_acceptance_label/models/stock_move_line.py Outdated
Flatten both _get_acceptance_numbers into an ordered de-duplication, drop
the status area wrapper in favour of calling the company from the label,
and seed the first operation through _prepare_move_line_vals rather than
overriding create.

The create override ran for every stock.move.line in the database and
browsed its move one record at a time, to cover paths that cannot carry
an acceptance number anyway. _prepare_move_line_vals covers the one that
matters, the operations built on confirmation. A hand-added operation no
longer inherits the number of its move, which is the only case lost.
@kanda999

Copy link
Copy Markdown
Author

I'd suggest splitting this module into two:

stock_acceptance_number: the acceptance number itself (detailed operations and transfer lines), the transfer search, and the related views. Depends on stock only.

stock_acceptance_number_label: the label report, the company settings (arrival date field, status area), and the settings view. Depends on stock_acceptance_number and product_expiry.

…n module

The acceptance number is useful on its own: it records what the goods were
received under, is kept on the lot, and is searched from the transfer
list. None of that needs a label, and the label was dragging product_expiry
into a database that only wanted the number.

stock_acceptance_number holds the number on the detailed operations, its
summary on the transfer line and the transfer, the numbers kept on the lot,
and the three views that show them. It depends on stock alone.

stock_acceptance_label keeps the report, the arrival date and status area
settings, and the two helpers that read a lot's expiration date and the
configured arrival date. It depends on stock_acceptance_number and, for the
expiration date, product_expiry.

The lot views are renamed to the name of the views they inherit, per the
view rule in AGENTS.md.
@nobuQuartile

Copy link
Copy Markdown
Contributor

They want to search for lots by acceptance_number while creating an MO.
The view is stock.quant, so I have added acceptance_number to stock.quant.
image

…icked

The components of a manufacturing order are picked from the quants, not
from the lots: the dialog lists a location, a lot and the quantity on
hand, and it is opened by quant_id rather than by lot_id.

The quant now carries the acceptance number of its lot, shown next to the
lot in the list the dialog opens and offered in its filter. Both pickers
are covered, as the full quant list inherits the simple one.

Toshikimi Shigenobu is credited on both modules.
@nobuQuartile
nobuQuartile force-pushed the 18.0-add-stock_acceptance_label branch from 2160a7b to 4366587 Compare September 30, 2026 08:35
@nobuQuartile nobuQuartile changed the title [7060][ADD] stock_acceptance_label: print acceptance labels from transfers [7060][ADD] stock_acceptance_number, stock_acceptance_label: print acceptance labels from transfers Sep 30, 2026

@AungKoKoLin1997 AungKoKoLin1997 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor points.

Comment thread stock_acceptance_label/readme/DESCRIPTION.md Outdated
Comment thread stock_acceptance_number/readme/USAGE.md Outdated
Comment thread stock_acceptance_number/models/stock_picking.py
@nobuQuartile
nobuQuartile force-pushed the 18.0-add-stock_acceptance_label branch 3 times, most recently from e8f741a to 7c454b1 Compare October 1, 2026 04:51
…pendencies

The description of the label named the module its number comes from, which
belongs with the dependency itself; the manifest says why each one is
there instead.

The quant says why it carries the number of its lot, which is not obvious
from a related field: the components of a manufacturing order are picked
from the quants, not from the lots.
@nobuQuartile
nobuQuartile force-pushed the 18.0-add-stock_acceptance_label branch from 7c454b1 to 4d9c4ef Compare October 1, 2026 06:18
Comment on lines +10 to +12
# The components of a manufacturing order are picked from the quants
# rather than from the lots, so the number of the lot has to be read
# and searched here as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about add like that in the readme?

When you select a lot-tracked component in the MO, you can search for it by acceptance number in the Quant view when adding a new line in Detailed Operations.

Suggested change
# The components of a manufacturing order are picked from the quants
# rather than from the lots, so the number of the lot has to be read
# and searched here as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants